home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / cplusinc / _string.h < prev    next >
Encoding:
C/C++ Source or Header  |  1994-12-18  |  34.9 KB  |  1,287 lines

  1. // This may look like C code, but it is really -*- C++ -*-
  2. /* 
  3. Copyright (C) 1988 Free Software Foundation
  4.     written by Doug Lea (dl@rocky.oswego.edu)
  5.  
  6. This file is part of the GNU C++ Library.  This library is free
  7. software; you can redistribute it and/or modify it under the terms of
  8. the GNU Library General Public License as published by the Free
  9. Software Foundation; either version 2 of the License, or (at your
  10. option) any later version.  This library is distributed in the hope
  11. that it will be useful, but WITHOUT ANY WARRANTY; without even the
  12. implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
  13. PURPOSE.  See the GNU Library General Public License for more details.
  14. You should have received a copy of the GNU Library General Public
  15. License along with this library; if not, write to the Free Software
  16. Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
  17. */
  18.  
  19.  
  20. #ifndef _String_h
  21. #ifdef __GNUG__
  22. #pragma interface
  23. #endif
  24. #define _String_h 1
  25.  
  26. #include <iostream.h>
  27. #ifndef __MSDOS__
  28. #include <Regex.h>
  29. #else
  30. #include <_Regex.h>
  31. #endif
  32.  
  33. struct StrRep                     // internal String representations
  34. {
  35.   unsigned short    len;         // string length 
  36.   unsigned short    sz;          // allocated space
  37.   char              s[1];        // the string starts here 
  38.                                  // (at least 1 char for trailing null)
  39.                                  // allocated & expanded via non-public fcts
  40. };
  41.  
  42. // primitive ops on StrReps -- nearly all String fns go through these.
  43.  
  44. StrRep*     Salloc(StrRep*, const char*, int, int);
  45. StrRep*     Scopy(StrRep*, const StrRep*);
  46. StrRep*     Scat(StrRep*, const char*, int, const char*, int);
  47. StrRep*     Scat(StrRep*, const char*, int,const char*,int, const char*,int);
  48. StrRep*     Sprepend(StrRep*, const char*, int);
  49. StrRep*     Sreverse(const StrRep*, StrRep*);
  50. StrRep*     Supcase(const StrRep*, StrRep*);
  51. StrRep*     Sdowncase(const StrRep*, StrRep*);
  52. StrRep*     Scapitalize(const StrRep*, StrRep*);
  53.  
  54. // These classes need to be defined in the order given
  55.  
  56. class String;
  57. class SubString;
  58.  
  59. class SubString
  60. {
  61.   friend class      String;
  62. protected:
  63.  
  64.   String&           S;        // The String I'm a substring of
  65.   unsigned short    pos;      // starting position in S's rep
  66.   unsigned short    len;      // length of substring
  67.  
  68.   void              assign(const StrRep*, const char*, int = -1);
  69.                     SubString(String& x, int p, int l);
  70.                     SubString(const SubString& x);
  71.  
  72. public:
  73.  
  74. // Note there are no public constructors. SubStrings are always
  75. // created via String operations
  76.  
  77.                    ~SubString();
  78.  
  79.   SubString&        operator =  (const String&     y);
  80.   SubString&        operator =  (const SubString&  y);
  81.   SubString&        operator =  (const char* t);
  82.   SubString&        operator =  (char        c);
  83.  
  84. // return 1 if target appears anywhere in SubString; else 0
  85.  
  86.   int               contains(char        c) const;
  87.   int               contains(const String&     y) const;
  88.   int               contains(const SubString&  y) const;
  89.   int               contains(const char* t) const;
  90.   int               contains(const Regex&       r) const;
  91.  
  92. // return 1 if target matches entire SubString
  93.  
  94.   int               matches(const Regex&  r) const;
  95.  
  96. // IO 
  97.  
  98.   friend ostream&   operator<<(ostream& s, const SubString& x);
  99.  
  100. // status
  101.  
  102.   unsigned int      length() const;
  103.   int               empty() const;
  104.   const char*       chars() const;
  105.  
  106.   int               OK() const; 
  107.  
  108. };
  109.  
  110.  
  111. class String
  112. {
  113.   friend class      SubString;
  114.  
  115. protected:
  116.   StrRep*           rep;   // Strings are pointers to their representations
  117.  
  118. // some helper functions
  119.  
  120.   int               search(int, int, const char*, int = -1) const;
  121.   int               search(int, int, char) const;
  122.   int               match(int, int, int, const char*, int = -1) const;
  123.   int               _gsub(const char*, int, const char* ,int);
  124.   int               _gsub(const Regex&, const char*, int);
  125.   SubString         _substr(int, int);
  126.  
  127. public:
  128.  
  129. // constructors & assignment
  130.  
  131.                     String();
  132.                     String(const String& x);
  133.                     String(const SubString&  x);
  134.                     String(const char* t);
  135.                     String(const char* t, int len);
  136.                     String(char c);
  137.  
  138.                     ~String();
  139.  
  140.   String&           operator =  (const String&     y);
  141.   String&           operator =  (const char* y);
  142.   String&           operator =  (char        c);
  143.   String&           operator =  (const SubString&  y);
  144.  
  145. // concatenation
  146.  
  147.   String&           operator += (const String&     y); 
  148.   String&           operator += (const SubString&  y);
  149.   String&           operator += (const char* t);
  150.   String&           operator += (char        c);
  151.  
  152.   void              prepend(const String&     y); 
  153.   void              prepend(const SubString&  y);
  154.   void              prepend(const char* t);
  155.   void              prepend(char        c);
  156.  
  157.  
  158. // procedural versions:
  159. // concatenate first 2 args, store result in last arg
  160.  
  161.   friend inline void     cat(const String&, const String&, String&);
  162.   friend inline void     cat(const String&, const SubString&, String&);
  163.   friend inline void     cat(const String&, const char*, String&);
  164.   friend inline void     cat(const String&, char, String&);
  165.  
  166.   friend inline void     cat(const SubString&, const String&, String&);
  167.   friend inline void     cat(const SubString&, const SubString&, String&);
  168.   friend inline void     cat(const SubString&, const char*, String&);
  169.   friend inline void     cat(const SubString&, char, String&);
  170.  
  171.   friend inline void     cat(const char*, const String&, String&);
  172.   friend inline void     cat(const char*, const SubString&, String&);
  173.   friend inline void     cat(const char*, const char*, String&);
  174.   friend inline void     cat(const char*, char, String&);
  175.  
  176. // double concatenation, by request. (yes, there are too many versions, 
  177. // but if one is supported, then the others should be too...)
  178. // Concatenate first 3 args, store in last arg
  179.  
  180.   friend inline void     cat(const String&,const String&, const String&,String&);
  181.   friend inline void     cat(const String&,const String&,const SubString&,String&);
  182.   friend inline void     cat(const String&,const String&, const char*, String&);
  183.   friend inline void     cat(const String&,const String&, char, String&);
  184.   friend inline void     cat(const String&,const SubString&,const String&,String&);
  185.   inline friend void     cat(const String&,const SubString&,const SubString&,String&);
  186.   friend inline void     cat(const String&,const SubString&, const char*, String&);
  187.   friend inline void     cat(const String&,const SubString&, char, String&);
  188.   friend inline void     cat(const String&,const char*, const String&,    String&);
  189.   friend inline void     cat(const String&,const char*, const SubString&, String&);
  190.   friend inline void     cat(const String&,const char*, const char*, String&);
  191.   friend inline void     cat(const String&,const char*, char, String&);
  192.  
  193.   friend inline void     cat(const char*, const String&, const String&,String&);
  194.   friend inline void     cat(const char*,const String&,const SubString&,String&);
  195.   friend inline void     cat(const char*,const String&, const char*, String&);
  196.   friend inline void     cat(const char*,const String&, char, String&);
  197.   friend inline void     cat(const char*,const SubString&,const String&,String&);
  198.   friend inline void     cat(const char*,const SubString&,const SubString&,String&);
  199.   friend inline void     cat(const char*,const SubString&, const char*, String&);
  200.   friend inline void     cat(const char*,const SubString&, char, String&);
  201.   friend inline void     cat(const char*,const char*, const String&,    String&);
  202.   friend inline void     cat(const char*,const char*, const SubString&, String&);
  203.   friend inline void     cat(const char*,const char*, const char*, String&);
  204.   friend inline void     cat(const char*,const char*, char, String&);
  205.  
  206.  
  207. // searching & matching
  208.  
  209. // return position of target in string or -1 for failure
  210.  
  211.   int               index(char        c, int startpos = 0) const;      
  212.   int               index(const String&     y, int startpos = 0) const;      
  213.   int               index(const SubString&  y, int startpos = 0) const;      
  214.   int               index(const char* t, int startpos = 0) const;  
  215.   int               index(const Regex&      r, int startpos = 0) const;       
  216.  
  217. // return 1 if target appears anyhere in String; else 0
  218.  
  219.   int               contains(char        c) const;
  220.   int               contains(const String&     y) const;
  221.   int               contains(const SubString&  y) const;
  222.   int               contains(const char* t) const;
  223.   int               contains(const Regex&      r) const;
  224.  
  225. // return 1 if target appears anywhere after position pos 
  226. // (or before, if pos is negative) in String; else 0
  227.  
  228.   int               contains(char        c, int pos) const;
  229.   int               contains(const String&     y, int pos) const;
  230.   int               contains(const SubString&  y, int pos) const;
  231.   int               contains(const char* t, int pos) const;
  232.   int               contains(const Regex&      r, int pos) const;
  233.  
  234. // return 1 if target appears at position pos in String; else 0
  235.  
  236.   int               matches(char        c, int pos = 0) const;
  237.   int               matches(const String&     y, int pos = 0) const;
  238.   int               matches(const SubString&  y, int pos = 0) const;
  239.   int               matches(const char* t, int pos = 0) const;
  240.   int               matches(const Regex&      r, int pos = 0) const;
  241.  
  242. //  return number of occurences of target in String
  243.  
  244.   int               freq(char        c) const; 
  245.   int               freq(const String&     y) const;
  246.   int               freq(const SubString&  y) const;
  247.   int               freq(const char* t) const;
  248.  
  249. // SubString extraction
  250.  
  251. // Note that you can't take a substring of a const String, since
  252. // this leaves open the possiblility of indirectly modifying the
  253. // String through the SubString
  254.  
  255.   SubString         at(int         pos, int len);
  256.   SubString         operator () (int         pos, int len); // synonym for at
  257.  
  258.   SubString         at(const String&     x, int startpos = 0); 
  259.   SubString         at(const SubString&  x, int startpos = 0); 
  260.   SubString         at(const char* t, int startpos = 0);
  261.   SubString         at(char        c, int startpos = 0);
  262.   SubString         at(const Regex&      r, int startpos = 0); 
  263.  
  264.   SubString         before(int          pos);
  265.   SubString         before(const String&      x, int startpos = 0);
  266.   SubString         before(const SubString&   x, int startpos = 0);
  267.   SubString         before(const char*  t, int startpos = 0);
  268.   SubString         before(char         c, int startpos = 0);
  269.   SubString         before(const Regex&       r, int startpos = 0);
  270.  
  271.   SubString         through(int          pos);
  272.   SubString         through(const String&      x, int startpos = 0);
  273.   SubString         through(const SubString&   x, int startpos = 0);
  274.   SubString         through(const char*  t, int startpos = 0);
  275.   SubString         through(char         c, int startpos = 0);
  276.   SubString         through(const Regex&       r, int startpos = 0);
  277.  
  278.   SubString         from(int          pos);
  279.   SubString         from(const String&      x, int startpos = 0);
  280.   SubString         from(const SubString&   x, int startpos = 0);
  281.   SubString         from(const char*  t, int startpos = 0);
  282.   SubString         from(char         c, int startpos = 0);
  283.   SubString         from(const Regex&       r, int startpos = 0);
  284.  
  285.   SubString         after(int         pos);
  286.   SubString         after(const String&     x, int startpos = 0);
  287.   SubString         after(const SubString&  x, int startpos = 0);
  288.   SubString         after(const char* t, int startpos = 0);
  289.   SubString         after(char        c, int startpos = 0);
  290.   SubString         after(const Regex&      r, int startpos = 0);
  291.  
  292.  
  293. // deletion
  294.  
  295. // delete len chars starting at pos
  296.   void              del(int         pos, int len);
  297.  
  298. // delete the first occurrence of target after startpos
  299.  
  300.   void              del(const String&     y, int startpos = 0);
  301.   void              del(const SubString&  y, int startpos = 0);
  302.   void              del(const char* t, int startpos = 0);
  303.   void              del(char        c, int startpos = 0);
  304.   void              del(const Regex&      r, int startpos = 0);
  305.  
  306. // global substitution: substitute all occurrences of pat with repl
  307.  
  308.   int               gsub(const String&     pat, const String&     repl);
  309.   int               gsub(const SubString&  pat, const String&     repl);
  310.   int               gsub(const char* pat, const String&     repl);
  311.   int               gsub(const char* pat, const char* repl);
  312.   int               gsub(const Regex&      pat, const String&     repl);
  313.  
  314. // friends & utilities
  315.  
  316. // split string into array res at separators; return number of elements
  317.  
  318.   friend int        split(const String& x, String res[], int maxn, 
  319.                           const String& sep);
  320.   friend int        split(const String& x, String res[], int maxn, 
  321.                           const Regex&  sep);
  322.  
  323.   friend String     common_prefix(const String& x, const String& y, 
  324.                                   int startpos = 0);
  325.   friend String     common_suffix(const String& x, const String& y, 
  326.                                   int startpos = -1);
  327.   friend String     replicate(char        c, int n);
  328.   friend String     replicate(const String&     y, int n);
  329.   friend String     join(String src[], int n, const String& sep);
  330.  
  331. // simple builtin transformations
  332.  
  333.   friend inline String     reverse(const String& x);
  334.   friend inline String     upcase(const String& x);
  335.   friend inline String     downcase(const String& x);
  336.   friend inline String     capitalize(const String& x);
  337.  
  338. // in-place versions of above
  339.  
  340.   void              reverse();
  341.   void              upcase();
  342.   void              downcase();
  343.   void              capitalize();
  344.  
  345. // element extraction
  346.  
  347.   char&             operator [] (int i);
  348.   const char&       operator [] (int i) const;
  349.   char              elem(int i) const;
  350.   char              firstchar() const;
  351.   char              lastchar() const;
  352.  
  353. // conversion
  354.  
  355.                     operator const char*() const;
  356.   const char*       chars() const;
  357.  
  358.  
  359. // IO
  360.  
  361.   friend inline ostream&   operator<<(ostream& s, const String& x);
  362.   friend ostream&   operator<<(ostream& s, const SubString& x);
  363.   friend istream&   operator>>(istream& s, String& x);
  364.  
  365.   friend int        readline(istream& s, String& x, 
  366.                              char terminator = '\n',
  367.                              int discard_terminator = 1);
  368.  
  369. // status
  370.  
  371.   unsigned int      length() const;
  372.   int               empty() const;
  373.  
  374. // preallocate some space for String
  375.   void              alloc(int newsize);
  376.  
  377. // report current allocation (not length!)
  378.  
  379.   int               allocation() const;
  380.  
  381.  
  382.   void     error(const char* msg) const;
  383.  
  384.   int               OK() const;
  385. };
  386.  
  387. typedef String StrTmp; // for backward compatibility
  388.  
  389. // other externs
  390.  
  391. int        compare(const String&    x, const String&     y);
  392. int        compare(const String&    x, const SubString&  y);
  393. int        compare(const String&    x, const char* y);
  394. int        compare(const SubString& x, const String&     y);
  395. int        compare(const SubString& x, const SubString&  y);
  396. int        compare(const SubString& x, const char* y);
  397. int        fcompare(const String&   x, const String&     y); // ignore case
  398.  
  399. extern StrRep  _nilStrRep;
  400. extern String _nilString;
  401.  
  402. // status reports, needed before defining other things
  403.  
  404. inline unsigned int String::length() const {  return rep->len; }
  405. inline int         String::empty() const { return rep->len == 0; }
  406. inline const char* String::chars() const { return &(rep->s[0]); }
  407. inline int         String::allocation() const { return rep->sz; }
  408.  
  409. inline unsigned int SubString::length() const { return len; }
  410. inline int         SubString::empty() const { return len == 0; }
  411. inline const char* SubString::chars() const { return &(S.rep->s[pos]); }
  412.  
  413.  
  414. // constructors
  415.  
  416. inline String::String() 
  417.   : rep(&_nilStrRep) {}
  418. inline String::String(const String& x) 
  419.   : rep(Scopy(0, x.rep)) {}
  420. inline String::String(const char* t) 
  421.   : rep(Salloc(0, t, -1, -1)) {}
  422. inline String::String(const char* t, int tlen)
  423.   : rep(Salloc(0, t, tlen, tlen)) {}
  424. inline String::String(const SubString& y)
  425.   : rep(Salloc(0, y.chars(), y.length(), y.length())) {}
  426. inline String::String(char c) 
  427.   : rep(Salloc(0, &c, 1, 1)) {}
  428.  
  429. inline String::~String() { if (rep != &_nilStrRep) delete rep; }
  430.  
  431. inline SubString::SubString(const SubString& x)
  432.   :S(x.S), pos(x.pos), len(x.len) {}
  433. inline SubString::SubString(String& x, int first, int l)
  434.   :S(x), pos(first), len(l) {}
  435.  
  436. inline SubString::~SubString() {}
  437.  
  438. // assignment
  439.  
  440. inline String& String::operator =  (const String& y)
  441.   rep = Scopy(rep, y.rep);
  442.   return *this;
  443. }
  444.  
  445. inline String& String::operator=(const char* t)
  446. {
  447.   rep = Salloc(rep, t, -1, -1);
  448.   return *this;
  449. }
  450.  
  451. inline String& String::operator=(const SubString&  y)
  452. {
  453.   rep = Salloc(rep, y.chars(), y.length(), y.length());
  454.   return *this;
  455. }
  456.  
  457. inline String& String::operator=(char c)
  458. {
  459.   rep = Salloc(rep, &c, 1, 1);
  460.   return *this;
  461. }
  462.  
  463.  
  464. inline SubString& SubString::operator = (const char* ys)
  465. {
  466.   assign(0, ys);
  467.   return *this;
  468. }
  469.  
  470. inline SubString& SubString::operator = (char ch)
  471. {
  472.   assign(0, &ch, 1);
  473.   return *this;
  474. }
  475.  
  476. inline SubString& SubString::operator = (const String& y)
  477. {
  478.   assign(y.rep, y.chars(), y.length());
  479.   return *this;
  480. }
  481.  
  482. inline SubString& SubString::operator = (const SubString& y)
  483. {
  484.   assign(y.S.rep, y.chars(), y.length());
  485.   return *this;
  486. }
  487.  
  488. // Zillions of cats...
  489.  
  490. inline void cat(const String& x, const String& y, String& r)
  491. {
  492.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  493. }
  494.  
  495. inline void cat(const String& x, const SubString& y, String& r)
  496. {
  497.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  498. }
  499.  
  500. inline void cat(const String& x, const char* y, String& r)
  501. {
  502.   r.rep = Scat(r.rep, x.chars(), x.length(), y, -1);
  503. }
  504.  
  505. inline void cat(const String& x, char y, String& r)
  506. {
  507.   r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1);
  508. }
  509.  
  510. inline void cat(const SubString& x, const String& y, String& r)
  511. {
  512.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  513. }
  514.  
  515. inline void cat(const SubString& x, const SubString& y, String& r)
  516. {
  517.   r.rep = Scat(r.rep, x.chars(), x.length(), y.chars(), y.length());
  518. }
  519.  
  520. inline void cat(const SubString& x, const char* y, String& r)
  521. {
  522.   r.rep = Scat(r.rep, x.chars(), x.length(), y, -1);
  523. }
  524.  
  525. inline void cat(const SubString& x, char y, String& r)
  526. {
  527.   r.rep = Scat(r.rep, x.chars(), x.length(), &y, 1);
  528. }
  529.  
  530. inline void cat(const char* x, const String& y, String& r)
  531. {
  532.   r.rep = Scat(r.rep, x, -1, y.chars(), y.length());
  533. }
  534.  
  535. inline void cat(const char* x, const SubString& y, String& r)
  536. {
  537.   r.rep = Scat(r.rep, x, -1, y.chars(), y.length());
  538. }
  539.  
  540. inline void cat(const char* x, const char* y, String& r)
  541. {
  542.   r.rep = Scat(r.rep, x, -1, y, -1);
  543. }
  544.  
  545. inline void cat(const char* x, char y, String& r)
  546. {
  547.   r.rep = Scat(r.rep, x, -1, &y, 1);
  548. }
  549.  
  550. inline void cat(const String& a, const String& x, const String& y, String& r)
  551. {
  552.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  553. }
  554.  
  555. inline void cat(const String& a, const String& x, const SubString& y, String& r)
  556. {
  557.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  558. }
  559.  
  560. inline void cat(const String& a, const String& x, const char* y, String& r)
  561. {
  562.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1);
  563. }
  564.  
  565. inline void cat(const String& a, const String& x, char y, String& r)
  566. {
  567.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1);
  568. }
  569.  
  570. inline void cat(const String& a, const SubString& x, const String& y, String& r)
  571. {
  572.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  573. }
  574.  
  575. inline void cat(const String& a, const SubString& x, const SubString& y, String& r)
  576. {
  577.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y.chars(), y.length());
  578. }
  579.  
  580. inline void cat(const String& a, const SubString& x, const char* y, String& r)
  581. {
  582.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), y, -1);
  583. }
  584.  
  585. inline void cat(const String& a, const SubString& x, char y, String& r)
  586. {
  587.   r.rep = Scat(r.rep, a.chars(), a.length(), x.chars(), x.length(), &y, 1);
  588. }
  589.  
  590. inline void cat(const String& a, const char* x, const String& y, String& r)
  591. {
  592.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length());
  593. }
  594.  
  595. inline void cat(const String& a, const char* x, const SubString& y, String& r)
  596. {
  597.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y.chars(), y.length());
  598. }
  599.  
  600. inline void cat(const String& a, const char* x, const char* y, String& r)
  601. {
  602.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, y, -1);
  603. }
  604.  
  605. inline void cat(const String& a, const char* x, char y, String& r)
  606. {
  607.   r.rep = Scat(r.rep, a.chars(), a.length(), x, -1, &y, 1);
  608. }
  609.  
  610.  
  611. inline void cat(const char* a, const String& x, const String& y, String& r)
  612. {
  613.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  614. }
  615.  
  616. inline void cat(const char* a, const String& x, const SubString& y, String& r)
  617. {
  618.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  619. }
  620.  
  621. inline void cat(const char* a, const String& x, const char* y, String& r)
  622. {
  623.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1);
  624. }
  625.  
  626. inline void cat(const char* a, const String& x, char y, String& r)
  627. {
  628.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1);
  629. }
  630.  
  631. inline void cat(const char* a, const SubString& x, const String& y, String& r)
  632. {
  633.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  634. }
  635.  
  636. inline void cat(const char* a, const SubString& x, const SubString& y, String& r)
  637. {
  638.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y.chars(), y.length());
  639. }
  640.  
  641. inline void cat(const char* a, const SubString& x, const char* y, String& r)
  642. {
  643.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), y, -1);
  644. }
  645.  
  646. inline void cat(const char* a, const SubString& x, char y, String& r)
  647. {
  648.   r.rep = Scat(r.rep, a, -1, x.chars(), x.length(), &y, 1);
  649. }
  650.  
  651. inline void cat(const char* a, const char* x, const String& y, String& r)
  652. {
  653.   r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length());
  654. }
  655.  
  656. inline void cat(const char* a, const char* x, const SubString& y, String& r)
  657. {
  658.   r.rep = Scat(r.rep, a, -1, x, -1, y.chars(), y.length());
  659. }
  660.  
  661. inline void cat(const char* a, const char* x, const char* y, String& r)
  662. {
  663.   r.rep = Scat(r.rep, a, -1, x, -1, y, -1);
  664. }
  665.  
  666. inline void cat(const char* a, const char* x, char y, String& r)
  667. {
  668.   r.rep = Scat(r.rep, a, -1, x, -1, &y, 1);
  669. }
  670.  
  671.  
  672. // operator versions
  673.  
  674. inline String& String::operator +=(const String& y)
  675. {
  676.   cat(*this, y, *this);
  677.   return *this;
  678. }
  679.  
  680. inline String& String::operator +=(const SubString& y)
  681. {
  682.   cat(*this, y, *this);
  683.   return *this;
  684. }
  685.  
  686. inline String& String::operator += (const char* y)
  687. {
  688.   cat(*this, y, *this);
  689.   return *this;
  690. }
  691.  
  692. inline String& String:: operator +=(char y)
  693. {
  694.   cat(*this, y, *this);
  695.   return *this;
  696. }
  697.  
  698. // constructive concatenation
  699.  
  700. #if defined(__GNUG__) && !defined(_G_NO_NRV)
  701.  
  702. inline String operator + (const String& x, const String& y) return r;
  703. {
  704.   cat(x, y, r);
  705. }
  706.  
  707. inline String operator + (const String& x, const SubString& y) return r;
  708. {
  709.   cat(x, y, r);
  710. }
  711.  
  712. inline String operator + (const String& x, const char* y) return r;
  713. {
  714.   cat(x, y, r);
  715. }
  716.  
  717. inline String operator + (const String& x, char y) return r;
  718. {
  719.   cat(x, y, r);
  720. }
  721.  
  722. inline String operator + (const SubString& x, const String& y) return r;
  723. {
  724.   cat(x, y, r);
  725. }
  726.  
  727. inline String operator + (const SubString& x, const SubString& y) return r;
  728. {
  729.   cat(x, y, r);
  730. }
  731.  
  732. inline String operator + (const SubString& x, const char* y) return r;
  733. {
  734.   cat(x, y, r);
  735. }
  736.  
  737. inline String operator + (const SubString& x, char y) return r;
  738. {
  739.   cat(x, y, r);
  740. }
  741.  
  742. inline String operator + (const char* x, const String& y) return r;
  743. {
  744.   cat(x, y, r);
  745. }
  746.  
  747. inline String operator + (const char* x, const SubString& y) return r;
  748. {
  749.   cat(x, y, r);
  750. }
  751.  
  752. inline String reverse(const String& x) return r;
  753. {
  754.   r.rep = Sreverse(x.rep, r.rep);
  755. }
  756.  
  757. inline String upcase(const String& x) return r;
  758. {
  759.   r.rep = Supcase(x.rep, r.rep);
  760. }
  761.  
  762. inline String downcase(const String& x) return r;
  763. {
  764.   r.rep = Sdowncase(x.rep, r.rep);
  765. }
  766.  
  767. inline String capitalize(const String& x) return r;
  768. {
  769.   r.rep = Scapitalize(x.rep, r.rep);
  770. }
  771.  
  772. #else /* NO_NRV */
  773.  
  774. inline String operator + (const String& x, const String& y)
  775. {
  776.   String r;  cat(x, y, r);  return r;
  777. }
  778.  
  779. inline String operator + (const String& x, const SubString& y) 
  780. {
  781.   String r; cat(x, y, r); return r;
  782. }
  783.  
  784. inline String operator + (const String& x, const char* y) 
  785. {
  786.   String r; cat(x, y, r); return r;
  787. }
  788.  
  789. inline String operator + (const String& x, char y) 
  790. {
  791.   String r; cat(x, y, r); return r;
  792. }
  793.  
  794. inline String operator + (const SubString& x, const String& y) 
  795. {
  796.   String r; cat(x, y, r); return r;
  797. }
  798.  
  799. inline String operator + (const SubString& x, const SubString& y) 
  800. {
  801.   String r; cat(x, y, r); return r;
  802. }
  803.  
  804. inline String operator + (const SubString& x, const char* y) 
  805. {
  806.   String r; cat(x, y, r); return r;
  807. }
  808.  
  809. inline String operator + (const SubString& x, char y) 
  810. {
  811.   String r; cat(x, y, r); return r;
  812. }
  813.  
  814. inline String operator + (const char* x, const String& y) 
  815. {
  816.   String r; cat(x, y, r); return r;
  817. }
  818.  
  819. inline String operator + (const char* x, const SubString& y) 
  820. {
  821.   String r; cat(x, y, r); return r;
  822. }
  823.  
  824. inline String reverse(const String& x) 
  825. {
  826.   String r; r.rep = Sreverse(x.rep, r.rep); return r;
  827. }
  828.  
  829. inline String upcase(const String& x) 
  830. {
  831.   String r; r.rep = Supcase(x.rep, r.rep); return r;
  832. }
  833.  
  834. inline String downcase(const String& x) 
  835. {
  836.   String r; r.rep = Sdowncase(x.rep, r.rep); return r;
  837. }
  838.  
  839. inline String capitalize(const String& x) 
  840. {
  841.   String r; r.rep = Scapitalize(x.rep, r.rep); return r;
  842. }
  843.  
  844. #endif
  845.  
  846. // prepend
  847.  
  848. inline void String::prepend(const String& y)
  849. {
  850.   rep = Sprepend(rep, y.chars(), y.length());
  851. }
  852.  
  853. inline void String::prepend(const char* y)
  854. {
  855.   rep = Sprepend(rep, y, -1); 
  856. }
  857.  
  858. inline void String::prepend(char y)
  859. {
  860.   rep = Sprepend(rep, &y, 1); 
  861. }
  862.  
  863. inline void String::prepend(const SubString& y)
  864. {
  865.   rep = Sprepend(rep, y.chars(), y.length());
  866. }
  867.  
  868. // misc transformations
  869.  
  870.  
  871. inline void String::reverse()
  872. {
  873.   rep = Sreverse(rep, rep);
  874. }
  875.  
  876.  
  877. inline void String::upcase()
  878. {
  879.   rep = Supcase(rep, rep);
  880. }
  881.  
  882.  
  883. inline void String::downcase()
  884. {
  885.   rep = Sdowncase(rep, rep);
  886. }
  887.  
  888.  
  889. inline void String::capitalize()
  890. {
  891.   rep = Scapitalize(rep, rep);
  892. }
  893.  
  894. // element extraction
  895.  
  896. inline char&  String::operator [] (int i) 
  897.   if (((unsigned)i) >= length()) error("invalid index");
  898.   return rep->s[i];
  899. }
  900.  
  901. inline const char&  String::operator [] (int i) const
  902.   if (((unsigned)i) >= length()) error("invalid index");
  903.   return rep->s[i];
  904. }
  905.  
  906. inline char  String::elem (int i) const
  907.   if (((unsigned)i) >= length()) error("invalid index");
  908.   return rep->s[i];
  909. }
  910.  
  911. inline char  String::firstchar() const
  912.   return elem(0);
  913. }
  914.  
  915. inline char  String::lastchar() const
  916.   return elem(length() - 1);
  917. }
  918.  
  919. // searching
  920.  
  921. inline int String::index(char c, int startpos) const
  922. {
  923.   return search(startpos, length(), c);
  924. }
  925.  
  926. inline int String::index(const char* t, int startpos) const
  927. {   
  928.   return search(startpos, length(), t);
  929. }
  930.  
  931. inline int String::index(const String& y, int startpos) const
  932. {   
  933.   return search(startpos, length(), y.chars(), y.length());
  934. }
  935.  
  936. inline int String::index(const SubString& y, int startpos) const
  937. {   
  938.   return search(startpos, length(), y.chars(), y.length());
  939. }
  940.  
  941. inline int String::index(const Regex& r, int startpos) const
  942. {
  943.   int unused;  return r.search(chars(), length(), unused, startpos);
  944. }
  945.  
  946. inline int String::contains(char c) const
  947. {
  948.   return search(0, length(), c) >= 0;
  949. }
  950.  
  951. inline int String::contains(const char* t) const
  952. {   
  953.   return search(0, length(), t) >= 0;
  954. }
  955.  
  956. inline int String::contains(const String& y) const
  957. {   
  958.   return search(0, length(), y.chars(), y.length()) >= 0;
  959. }
  960.  
  961. inline int String::contains(const SubString& y) const
  962. {   
  963.   return search(0, length(), y.chars(), y.length()) >= 0;
  964. }
  965.  
  966. inline int String::contains(char c, int p) const
  967. {
  968.   return match(p, length(), 0, &c, 1) >= 0;
  969. }
  970.  
  971. inline int String::contains(const char* t, int p) const
  972. {
  973.   return match(p, length(), 0, t) >= 0;
  974. }
  975.  
  976. inline int String::contains(const String& y, int p) const
  977. {
  978.   return match(p, length(), 0, y.chars(), y.length()) >= 0;
  979. }
  980.  
  981. inline int String::contains(const SubString& y, int p) const
  982. {
  983.   return match(p, length(), 0, y.chars(), y.length()) >= 0;
  984. }
  985.  
  986. inline int String::contains(const Regex& r) const
  987. {
  988.   int unused;  return r.search(chars(), length(), unused, 0) >= 0;
  989. }
  990.  
  991. inline int String::contains(const Regex& r, int p) const
  992. {
  993.   return r.match(chars(), length(), p) >= 0;
  994. }
  995.  
  996.  
  997. inline int String::matches(const SubString& y, int p) const
  998. {
  999.   return match(p, length(), 1, y.chars(), y.length()) >= 0;
  1000. }
  1001.  
  1002. inline int String::matches(const String& y, int p) const
  1003. {
  1004.   return match(p, length(), 1, y.chars(), y.length()) >= 0;
  1005. }
  1006.  
  1007. inline int String::matches(const char* t, int p) const
  1008. {
  1009.   return match(p, length(), 1, t) >= 0;
  1010. }
  1011.  
  1012. inline int String::matches(char c, int p) const
  1013. {
  1014.   return match(p, length(), 1, &c, 1) >= 0;
  1015. }
  1016.  
  1017. inline int String::matches(const Regex& r, int p) const
  1018. {
  1019.   int l = (p < 0)? -p : length() - p;
  1020.   return r.match(chars(), length(), p) == l;
  1021. }
  1022.  
  1023.  
  1024. inline int SubString::contains(const char* t) const
  1025. {   
  1026.   return S.search(pos, pos+len, t) >= 0;
  1027. }
  1028.  
  1029. inline int SubString::contains(const String& y) const
  1030. {   
  1031.   return S.search(pos, pos+len, y.chars(), y.length()) >= 0;
  1032. }
  1033.  
  1034. inline int SubString::contains(const SubString&  y) const
  1035. {   
  1036.   return S.search(pos, pos+len, y.chars(), y.length()) >= 0;
  1037. }
  1038.  
  1039. inline int SubString::contains(char c) const
  1040. {
  1041.   return S.search(pos, pos+len, c) >= 0;
  1042. }
  1043.  
  1044. inline int SubString::contains(const Regex& r) const
  1045. {
  1046.   int unused;  return r.search(chars(), len, unused, 0) >= 0;
  1047. }
  1048.  
  1049. inline int SubString::matches(const Regex& r) const
  1050. {
  1051.   return r.match(chars(), len, 0) == len;
  1052. }
  1053.  
  1054.  
  1055. inline int String::gsub(const String& pat, const String& r)
  1056. {
  1057.   return _gsub(pat.chars(), pat.length(), r.chars(), r.length());
  1058. }
  1059.  
  1060. inline int String::gsub(const SubString&  pat, const String& r)
  1061. {
  1062.   return _gsub(pat.chars(), pat.length(), r.chars(), r.length());
  1063. }
  1064.  
  1065. inline int String::gsub(const Regex& pat, const String& r)
  1066. {
  1067.   return _gsub(pat, r.chars(), r.length());
  1068. }
  1069.  
  1070. inline int String::gsub(const char* pat, const String& r)
  1071. {
  1072.   return _gsub(pat, -1, r.chars(), r.length());
  1073. }
  1074.  
  1075. inline int String::gsub(const char* pat, const char* r)
  1076. {
  1077.   return _gsub(pat, -1, r, -1);
  1078. }
  1079.  
  1080.  
  1081.  
  1082. inline  ostream& operator<<(ostream& s, const String& x)
  1083. {
  1084.    s << x.chars(); return s;
  1085. }
  1086.  
  1087. // a zillion comparison operators
  1088.  
  1089. inline int operator==(const String& x, const String& y) 
  1090. {
  1091.   return compare(x, y) == 0; 
  1092. }
  1093.  
  1094. inline int operator!=(const String& x, const String& y)
  1095. {
  1096.   return compare(x, y) != 0; 
  1097. }
  1098.  
  1099. inline int operator>(const String& x, const String& y)
  1100. {
  1101.   return compare(x, y) > 0; 
  1102. }
  1103.  
  1104. inline int operator>=(const String& x, const String& y)
  1105. {
  1106.   return compare(x, y) >= 0; 
  1107. }
  1108.  
  1109. inline int operator<(const String& x, const String& y)
  1110. {
  1111.   return compare(x, y) < 0; 
  1112. }
  1113.  
  1114. inline int operator<=(const String& x, const String& y)
  1115. {
  1116.   return compare(x, y) <= 0; 
  1117. }
  1118.  
  1119. inline int operator==(const String& x, const SubString&  y) 
  1120. {
  1121.   return compare(x, y) == 0; 
  1122. }
  1123.  
  1124. inline int operator!=(const String& x, const SubString&  y)
  1125. {
  1126.   return compare(x, y) != 0; 
  1127. }
  1128.  
  1129. inline int operator>(const String& x, const SubString&  y)      
  1130. {
  1131.   return compare(x, y) > 0; 
  1132. }
  1133.  
  1134. inline int operator>=(const String& x, const SubString&  y)
  1135. {
  1136.   return compare(x, y) >= 0; 
  1137. }
  1138.  
  1139. inline int operator<(const String& x, const SubString&  y) 
  1140. {
  1141.   return compare(x, y) < 0; 
  1142. }
  1143.  
  1144. inline int operator<=(const String& x, const SubString&  y)
  1145. {
  1146.   return compare(x, y) <= 0; 
  1147. }
  1148.  
  1149. inline int operator==(const String& x, const char* t) 
  1150. {
  1151.   return compare(x, t) == 0; 
  1152. }
  1153.  
  1154. inline int operator!=(const String& x, const char* t) 
  1155. {
  1156.   return compare(x, t) != 0; 
  1157. }
  1158.  
  1159. inline int operator>(const String& x, const char* t)  
  1160. {
  1161.   return compare(x, t) > 0; 
  1162. }
  1163.  
  1164. inline int operator>=(const String& x, const char* t) 
  1165. {
  1166.   return compare(x, t) >= 0; 
  1167. }
  1168.  
  1169. inline int operator<(const String& x, const char* t)  
  1170. {
  1171.   return compare(x, t) < 0; 
  1172. }
  1173.  
  1174. inline int operator<=(const String& x, const char* t) 
  1175. {
  1176.   return compare(x, t) <= 0; 
  1177. }
  1178.  
  1179. inline int operator==(const SubString& x, const String& y) 
  1180. {
  1181.   return compare(y, x) == 0; 
  1182. }
  1183.  
  1184. inline int operator!=(const SubString& x, const String& y)
  1185. {
  1186.   return compare(y, x) != 0;
  1187. }
  1188.  
  1189. inline int operator>(const SubString& x, const String& y)      
  1190. {
  1191.   return compare(y, x) < 0;
  1192. }
  1193.  
  1194. inline int operator>=(const SubString& x, const String& y)     
  1195. {
  1196.   return compare(y, x) <= 0;
  1197. }
  1198.  
  1199. inline int operator<(const SubString& x, const String& y)      
  1200. {
  1201.   return compare(y, x) > 0;
  1202. }
  1203.  
  1204. inline int operator<=(const SubString& x, const String& y)     
  1205. {
  1206.   return compare(y, x) >= 0;
  1207. }
  1208.  
  1209. inline int operator==(const SubString& x, const SubString&  y) 
  1210. {
  1211.   return compare(x, y) == 0; 
  1212. }
  1213.  
  1214. inline int operator!=(const SubString& x, const SubString&  y)
  1215. {
  1216.   return compare(x, y) != 0;
  1217. }
  1218.  
  1219. inline int operator>(const SubString& x, const SubString&  y)      
  1220. {
  1221.   return compare(x, y) > 0;
  1222. }
  1223.  
  1224. inline int operator>=(const SubString& x, const SubString&  y)
  1225. {
  1226.   return compare(x, y) >= 0;
  1227. }
  1228.  
  1229. inline int operator<(const SubString& x, const SubString&  y) 
  1230. {
  1231.   return compare(x, y) < 0;
  1232. }
  1233.  
  1234. inline int operator<=(const SubString& x, const SubString&  y)
  1235. {
  1236.   return compare(x, y) <= 0;
  1237. }
  1238.  
  1239. inline int operator==(const SubString& x, const char* t) 
  1240. {
  1241.   return compare(x, t) == 0; 
  1242. }
  1243.  
  1244. inline int operator!=(const SubString& x, const char* t) 
  1245. {
  1246.   return compare(x, t) != 0;
  1247. }
  1248.  
  1249. inline int operator>(const SubString& x, const char* t)  
  1250. {
  1251.   return compare(x, t) > 0; 
  1252. }
  1253.  
  1254. inline int operator>=(const SubString& x, const char* t) 
  1255. {
  1256.   return compare(x, t) >= 0; 
  1257. }
  1258.  
  1259. inline int operator<(const SubString& x, const char* t)  
  1260. {
  1261.   return compare(x, t) < 0; 
  1262. }
  1263.  
  1264. inline int operator<=(const SubString& x, const char* t) 
  1265. {
  1266.   return compare(x, t) <= 0; 
  1267. }
  1268.  
  1269.  
  1270. // a helper needed by at, before, etc.
  1271.  
  1272. inline SubString String::_substr(int first, int l)
  1273. {
  1274.   if (first < 0 || (unsigned)(first + l) > length() )
  1275.     return SubString(_nilString, 0, 0) ;
  1276.   else 
  1277.     return SubString(*this, first, l);
  1278. }
  1279.  
  1280. #endif
  1281.